﻿using System.Collections.Generic;
using System.Windows.Forms;
using System.Xml;
using SdmxMl.Helper;
using SdmxMl.Common;

namespace SdmxMl.Structure
{
    /// <summary>
    /// A hierarchical codelist references a Codelist, and supplies the extra structural
    /// metadata to assemble the codes into a hierarchy. A human-readable name must be
    /// supplied, and multiple language-specific variants may be provided. A longer human
    /// -readable description may be provided, and may also be presented as a set of
    /// language-specific variants. The CodelistRef element references a codelist, and may
    /// indicate more than one. Annotations may be provided in the Annotaions element.
    /// An ID unique for the agency specified in the agency attribute must be assigned,
    /// using the id attribute. A version may be provided using the version attribute -
    /// if no value is provided, it is assumed to be "1.0". A valid SDMX Registry URN may
    /// be provided in the urn attribute, as specified in the SDMX Registry Specification.
    /// If the isExternalReference attribute has a value of true, the uri attribute must
    /// specify the location of a valid SDMX Structure Message which provides the full
    /// details of the hierarchical codelist; otherwise, all details must be present.
    /// The validFrom and validTo attributes provide inclusive dates for providing
    /// supplemental validity information about the version.
    /// </summary>
    public class HierarchicalCodelistType : Artefact, ISdmxDelChild, ISdmxNewChild
    {
        #region Properties
        public override ArtefactRefTypedList ArtefactRefList
        {
            get 
            {
                ArtefactRefTypedList list = new ArtefactRefTypedList();
                foreach (CodelistRefType crt in CodelistRefList)
                    list.Add(new ArtefactRefTyped(
                        SdmxMl.Manager.SdmxArtefactType.CodeLists, crt.Id, crt.AgencyId, crt.Version));

                return list;
            }
        }

        private CodelistRefTypeList _codelistRefList;
        public CodelistRefTypeList CodelistRefList
        {
            get { return _codelistRefList; }
        }

        private HierarchyTypeList _hierarchyList;
        public HierarchyTypeList HierarchyList
        {
            get { return _hierarchyList; }
        }

        
        #endregion //Properties

        #region Constructors
        
        private void Init()
        {
            _codelistRefList = new CodelistRefTypeList();
            _hierarchyList = new HierarchyTypeList();
        }


        public HierarchicalCodelistType()
        {
            Init();
            // Create one hierarchy for Edit
            CreateDefaultHierarchy();
        }

        private void CreateDefaultHierarchy()
        {
            // Create one hierarchy for Edit
            HierarchyType h = new HierarchyType(_codelistRefList);
            h.Id = "Undefined";
            h.Name.TextList.Add(new TextType(LangSupport.CurLang, "To be defined."));
            _hierarchyList.Add(h);
        }

        public HierarchicalCodelistType(XmlNode nodeArtefact, SdmxNamespaceManager nsmgr) 
            : base(nodeArtefact, nsmgr)
        {
            Init();
            string query = (nsmgr.VersionSdmx == SdmxVersion.SDMX_20) ?
                "./structure:CodelistRef" : "./structure:IncludedCodelist";
           

            XmlNodeList nodeList = nodeArtefact.SelectNodes(query, nsmgr);
            if (nodeList.Count > 0)
            {
                foreach (XmlNode nd in nodeList)
                {
                    CodelistRefType cr = new CodelistRefType(nd, nsmgr, null, false);
                    _codelistRefList.Add(cr);
                }
            }

            query ="./structure:Hierarchy";
            nodeList = nodeArtefact.SelectNodes(query, nsmgr);
            if (nodeList.Count > 0)
            {
                foreach (XmlNode nd in nodeList)
                {
                    HierarchyType h = new HierarchyType(_codelistRefList, nd, nsmgr);
                    _hierarchyList.Add(h);
                }
            }
            else
            {
                // Create one hierarchy for Edit
                CreateDefaultHierarchy();
            }
        }

        #endregion // Constructors

        #region XML serialize

        public override void WriteXmlInsider(XmlTextWriter xw)
        {
            string prefix = "structure";

            if (_codelistRefList.Count > 0)
            {
                foreach (CodelistRefType cr in _codelistRefList)
                    cr.WriteXml(xw, prefix, "CodelistRef");

                if (_hierarchyList.Count > 0)
                    foreach (HierarchyType h in _hierarchyList)
                        h.WriteXml(xw, prefix, "Hierarchy");
            }
        }

        #endregion

        #region Tree

        public override TreeNode FillNode(TreeNode parentNode)
        {
            TreeNode t = base.FillNode(parentNode);
            TreeNode td = new TreeNode(CodelistRefList.ToString(), 0, 0);
            t.Nodes.Add(td);
            td.Tag = CodelistRefList;

            foreach (HierarchyType h in _hierarchyList)
                h.FillNode(t);

            return t;
        }

        #endregion // Tree

        #region Artefact Type

        public override Manager.SdmxArtefactType ArType
        {
            get { return Manager.SdmxArtefactType.HierarchicalCodelists; }
        }

        #endregion


        #region ISdmxDelChild Members

        public void DelChild(object o)
        {
            HierarchyType h = o as HierarchyType;
            if (h != null)
                _hierarchyList.Remove(h);
        }

        #endregion

        #region ISdmxNewChild Members

        public TreeNode NewChild(TreeNode node)
        {
            TreeNode t = null;

            // Create one hierarchy for Edit
            HierarchyType h = new HierarchyType(_codelistRefList);
            h.Id = "Undefined";
            h.Name.TextList.Add(new TextType(LangSupport.CurLang, "To be defined."));
            _hierarchyList.Add(h);

            t = h.FillNode(node);
            return t;
        }

        #endregion
    }
}
